package admin

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"

	"suci-go-zero/common/ctxdata"
	"suci-go-zero/common/xerr"
	"suci-go-zero/internal/model"
	"suci-go-zero/internal/svc"
	"suci-go-zero/internal/types"

	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
)

type MyMenuLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewMyMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MyMenuLogic {
	return &MyMenuLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *MyMenuLogic) MyMenu() (resp *types.MyMenu, err error) {
	uid := ctxdata.GetUidFromCtx(l.ctx)
	//查找角色
	user, err := l.svcCtx.Models.User.FindOne(l.ctx, uid)
	if err != nil && err != model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "user-role 查找失败%v", err)
	}

	if err == model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_NOT_EXIST), "用户角色未查到")
	}

	rb := l.svcCtx.Models.Role.RowBuilder().Where(fmt.Sprintf("id in (?)", user.Roles))
	roles, err := l.svcCtx.Models.Role.FindAll(l.ctx, rb, "")

	if err != nil && err != model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "user-role 查找失败%v", err)
	}

	if err == model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_NOT_EXIST), "用户角色未查到")
	}

	menuIdArry := make([]string, 0)
	for _, role := range roles {
		menuIdArry = append(menuIdArry, fmt.Sprintf("%d", role.Menus))
	}
	menuIdStr := strings.Join(menuIdArry, ",")

	rb = l.svcCtx.Models.Menu.RowBuilder().Where(fmt.Sprintf("id in %s", menuIdStr))
	menuList, err := l.svcCtx.Models.Menu.FindAll(l.ctx, rb, "sort desc")
	if err != nil && err != model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "菜单 数据库错误%v", err)
	}

	if err == model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_NOT_FOUND_ERR), "菜单列表为空%v", err)
	}

	li := make([]*types.MenuItem, 0)
	for _, mi := range menuList {
		meta := &types.Meta{}
		err = json.Unmarshal([]byte(mi.Meta), meta)
		if err != nil {
			logx.Info(err)
		}
		mn := &types.MenuItem{
			Id:        mi.Id,
			Pid:       mi.ParentId,
			Name:      mi.Name,
			Path:      mi.Path,
			Meta:      *meta,
			Component: mi.Component,
		}
		li = append(li, mn)
	}

	li = getTreeRecursive(li, 0)

	resp = &types.MyMenu{
		Menu: li,
		Permissions: []string{"list.add",
			"list.edit",
			"list.delete",
			"user.add",
			"user.edit",
			"user.delete",
		},
	}

	return resp, nil
}

func getTreeRecursive(list []*types.MenuItem, FatherId int) []*types.MenuItem {
	res := make([]*types.MenuItem, 0)
	for _, v := range list {
		if int(v.Pid) == FatherId {
			v.Children = getTreeRecursive(list, int(v.Id))
			res = append(res, v)
		}
	}
	return res
}
